﻿
Imports std
Imports storoomc
Imports storcore.storoomCallbackManager

Public MustInherit Class storoomSingleThreadTM
    Implements storoomThreadModel

    Private caller As storoomOper(Of storoomSingleThreadTM) = Nothing
    Private cbm As storoomCallbackManager = Nothing

    Public Sub New(ByVal caller As storoomOper(Of storoomSingleThreadTM))
        assert(Not caller Is Nothing)
        Me.caller = caller
        cbm = New storoomCallbackManager()
    End Sub

    Private Function oper(Of ROUND_RESULT_T, TOTAL_RESULT_T) _
                         (ByVal d As _do(Of storageInterface, ROUND_RESULT_T, TOTAL_RESULT_T, Boolean),
                          ByVal cb As _do(Of storageInterface, Boolean, ROUND_RESULT_T, Boolean),
                          ByVal s As storageInterface,
                          ByVal jobType As jobType,
                          Optional ByRef total As TOTAL_RESULT_T = Nothing,
                          Optional ByVal needFailureMessage As Boolean = True) As Boolean
        assert(Not d Is Nothing)
        assert(Not cb Is Nothing)
        assert(Not s Is Nothing)
        Dim rtn As Boolean = False
        Dim rst As ROUND_RESULT_T = Nothing
        rtn = d(s, rst, total)
        If Not cb(s, rtn, rst) Then
            raiseError(errorHandle.errorType.exclamation,
                       "cannot run ", jobType_String(jobType), " callback on slice ", caller.showslice(s))
        End If
        If Not rtn Then
            If needFailureMessage Then
                raiseError(errorHandle.errorType.exclamation,
                           "cannot run ", jobType_String(jobType), " on slice ", caller.showslice(s))
            End If
            Return False
        Else
            Return True
        End If
    End Function

    Private Function oper(Of ROUND_RESULT_T, TOTAL_RESULT_T) _
                         (ByVal d As _do(Of storageInterface, ROUND_RESULT_T, TOTAL_RESULT_T, Boolean),
                          ByVal cb As _do(Of storageInterface, Boolean, ROUND_RESULT_T, Boolean),
                          ByVal slices As vector(Of storageInterface),
                          ByVal jobType As jobType,
                          Optional ByRef total As TOTAL_RESULT_T = Nothing,
                          Optional ByVal needFailureMessage As Boolean = True) As Boolean
        If slices Is Nothing OrElse slices.size() = 0 Then
            Return False
        End If

        Dim start As Int64 = 0
        Dim i As Int64 = 0
        start = rnd(0, slices.size(), True)
        i = start
        Do
            If Not oper(d, cb, slices(i), jobType, total, needFailureMessage) Then
                Return False
            End If

            i += 1
            If i = slices.size() Then
                i = 0
            End If
        Loop Until i = start

        Return True
    End Function

    Private Sub oper_until_fail(Of ROUND_RESULT_T, TOTAL_RESULT_T) _
                               (ByVal d As _do(Of storageInterface, ROUND_RESULT_T, TOTAL_RESULT_T, Boolean),
                                ByVal cb As _do(Of storageInterface, Boolean, ROUND_RESULT_T, Boolean),
                                ByVal slices As vector(Of storageInterface),
                                ByVal jobType As jobType,
                                Optional ByRef total As TOTAL_RESULT_T = Nothing)
        oper(d, cb, slices, jobType, total, False)
    End Sub

    Private Sub oper_until_succ(Of ROUND_RESULT_T, TOTAL_RESULT_T) _
                               (ByVal d As _do(Of storageInterface, ROUND_RESULT_T, TOTAL_RESULT_T, Boolean),
                                ByVal cb As _do(Of storageInterface, Boolean, ROUND_RESULT_T, Boolean),
                                ByVal slices As vector(Of storageInterface),
                                ByVal jobType As jobType,
                                Optional ByRef total As TOTAL_RESULT_T = Nothing)
        assert(Not d Is Nothing)
        oper(Function(ByRef si As storageInterface,
                      ByRef rst As ROUND_RESULT_T,
                      ByRef t As TOTAL_RESULT_T) As Boolean
                 Return Not d(si, rst, t)
             End Function, cb, slices, jobType, total, False)
    End Sub

    Public Function capacity(ByRef cap As UInt64,
                             ByVal slices As vector(Of storageInterface)) As Boolean _
                            Implements storoomThreadModel.capacity
        Dim p As capacityParameter = Nothing
        If oper(Function(ByRef s As storageInterface, ByRef this As UInt64, ByRef total As UInt64) As Boolean
                    If s.capacity(this) Then
                        total += this
                        Return True
                    Else
                        Return False
                    End If
                End Function,
                Function(ByRef s As storageInterface, ByRef rst As Boolean, ByRef this As UInt64) As Boolean
                    Return cbm.capacity(s, rst, this, p)
                End Function,
                slices, jobType.capacity, cap) Then
            Return True
        Else
            Return False
        End If
    End Function

    Public Function shareTypeCapacity(ByRef cap As UInt64,
                                      ByVal slices As vector(Of storageInterface)) As Boolean _
                                     Implements storoomThreadModel.shareTypeCapacity
        Dim p As capacityParameter = Nothing
        If oper(Function(ByRef s As storageInterface, ByRef this As UInt64, ByRef total As UInt64) As Boolean
                    If s.capacity(this) Then
                        If total > this Then
                            total = this
                        End If
                    Else
                        total = 0
                    End If
                    Return True
                End Function,
                Function(ByRef s As storageInterface, ByRef rst As Boolean, ByRef this As UInt64) As Boolean
                    Return cbm.capacity(s, rst, this, p)
                End Function,
                slices, jobType.capacity, cap) Then
            Return True
        Else
            Return False
        End If
    End Function

    Public Function close(ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.close
        Dim p As closeParameter = Nothing
        Return oper(Function(ByRef s As storageInterface, ByRef _NIU_ As Object, ByRef _NIU2_ As Object) As Boolean
                        Return s.close()
                    End Function,
                    Function(ByRef s As storageInterface, ByRef rst As Boolean, ByRef _NIU_ As Object) As Boolean
                        Return cbm.close(s, rst, p)
                    End Function,
                    slices, jobType.close)
    End Function

    Public Function delete(ByVal key As String,
                           ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.delete
        Dim rtn As Boolean = False
        Dim p As deleteParameter = Nothing
        If oper(Function(ByRef s As storageInterface, ByRef _NIU_ As Object, ByRef _NIU2_ As Object) As Boolean
                    If s.delete(key) Then
                        rtn = True
                    End If
                    Return True
                End Function,
                Function(ByRef s As storageInterface, ByRef rst As Boolean, ByRef _NIU_ As Object) As Boolean
                    Return cbm.delete(s, key, rst, p)
                End Function,
                slices, jobType.delete) Then
            Return rtn
        Else
            Return False
        End If
    End Function

    'if one is not empty, treat as not empty
    Public Function empty(ByVal slices As vector(Of storageInterface)) As ternary Implements storoomThreadModel.empty
        Dim rtn As Boolean = True
        Dim p As emptyParameter = Nothing
        oper_until_fail(Function(ByRef s As storageInterface, ByRef _NIU_ As Object, ByRef _NIU2_ As Object) As Boolean
                            rtn = rtn And s.empty()
                            Return rtn
                        End Function,
                        Function(ByRef s As storageInterface, ByRef rst As Boolean, ByRef _NIU_ As Object) As Boolean
                            Return cbm.empty(s, rst, p)
                        End Function, slices, jobType.empty)
        Return ifoper(rtn, ternary.true, ternary.false)
    End Function

    'if one is not full, treat as not full
    Public Function full(ByVal slices As vector(Of storageInterface)) As ternary Implements storoomThreadModel.full
        Dim rtn As Boolean = True
        Dim p As fullParameter = Nothing
        oper_until_fail(Function(ByRef s As storageInterface, ByRef _NIU_ As Object, ByRef _NIU2_ As Object) As Boolean
                            rtn = rtn And s.full()
                            Return rtn
                        End Function,
                        Function(ByRef s As storageInterface, ByRef rst As Boolean, ByRef _NIU_ As Object) As Boolean
                            Return cbm.full(s, rst, p)
                        End Function, slices, jobType.full)
        Return ifoper(rtn, ternary.true, ternary.false)
    End Function

    'if one is full, treat as full
    Public Function shareTypeFull(ByVal slices As vector(Of storageInterface)) As ternary _
                                 Implements storoomThreadModel.shareTypeFull
        Dim rtn As Boolean = False
        Dim p As fullParameter = Nothing
        oper_until_succ(Function(ByRef s As storageInterface, ByRef _NIU_ As Object, ByRef _NIU2_ As Object) As Boolean
                            rtn = rtn Or s.full()
                            Return rtn
                        End Function,
                        Function(ByRef s As storageInterface, ByRef rst As Boolean, ByRef _NIU_ As Object) As Boolean
                            Return cbm.full(s, rst, p)
                        End Function, slices, jobType.full)
        Return ifoper(rtn, ternary.true, ternary.false)
    End Function

    Public Function keycount(ByRef count As UInt64,
                             ByVal slices As vector(Of storageInterface)) As Boolean _
                            Implements storoomThreadModel.keycount
        Dim p As keycountParameter = Nothing
        If oper(Function(ByRef s As storageInterface, ByRef this As UInt64, ByRef total As UInt64) As Boolean
                    If s.keycount(this) Then
                        total += this
                        Return True
                    Else
                        Return False
                    End If
                End Function,
                Function(ByRef s As storageInterface, ByRef rst As Boolean, ByRef this As UInt64) As Boolean
                    Return cbm.keycount(s, rst, this, p)
                End Function, slices, jobType.keycount, count) Then
            Return True
        Else
            Return False
        End If
    End Function

    Public Function list(ByVal l As vector(Of String),
                         ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.list
        Return oper(Function(ByRef s As storageInterface, ByRef __NOT_IN_USE__ As Object) As Boolean
                        Dim tmp As vector(Of String) = Nothing
                        If s.list(tmp) Then
                            l.push_back(tmp)
                            Return True
                        Else
                            Return False
                        End If
                    End Function, slices, jobType.list, Nothing)
    End Function

    Public Function open(ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.open
        Return oper(Function(ByRef s As storageInterface, ByRef __NOT_IN_USE__ As Object) As Boolean
                        Return s.open()
                    End Function, slices, jobType.open, Nothing)
    End Function

    Public Function read(ByVal key As String,
                         ByRef buff As bytes,
                         ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.read
        If oper(Function(ByRef s As storageInterface, ByRef b As bytes) As Boolean
                    Dim tmp As bytes = Nothing
                    If s.read(key, tmp) Then
                        b += tmp
                    End If
                    Return True
                End Function, slices, jobType.read, buff) Then
            Return Not buff Is Nothing
        Else
            Return False
        End If
    End Function

    Public Function retire(ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.retire
        Return oper(Function(ByRef s As storageInterface, ByRef __NOT_IN_USE__ As Object) As Boolean
                        Return s.retire()
                    End Function, slices, jobType.retire, Nothing)
    End Function

    Public Function seek(ByVal key As String,
                         ByVal slices As vector(Of storageInterface)) As ternary Implements storoomThreadModel.seek
        Dim rtn As Boolean = False
        oper(Function(ByRef s As storageInterface, ByRef __NOT_IN_USE__ As Object) As Boolean
                 If s.seek(key) Then
                     rtn = True
                     Return False
                 Else
                     Return True
                 End If
             End Function, slices, jobType.seek, Nothing)

        Return ifoper(rtn, ternary.true, ternary.false)
    End Function

    Public Function sizeof(ByVal key As String,
                           ByRef size As UInt64,
                           ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.sizeof
        Dim rtn As Boolean = False
        If oper(Function(ByRef s As storageInterface, ByRef sz As UInt64) As Boolean
                    Dim tmp As UInt64 = 0
                    If s.sizeof(key, tmp) Then
                        rtn = True
                        sz += tmp
                    End If
                    Return True
                End Function, slices, jobType.sizeof, size) Then
            Return rtn
        Else
            Return False
        End If
    End Function

    Public Function valuesize(ByRef size As UInt64,
                              ByVal slices As vector(Of storageInterface)) As Boolean _
                             Implements storoomThreadModel.valuesize
        Dim rtn As Boolean = True
        If oper(Function(ByRef s As storageInterface, ByRef sz As UInt64) As Boolean
                    Dim tmp As UInt64 = 0
                    If s.valuesize(tmp) Then
                        sz += tmp
                        Return True
                    Else
                        Return False
                    End If
                End Function, slices, jobType.valuesize, size) Then
            Return True
        Else
            Return False
        End If
    End Function

    Public Function write(ByVal key As String,
                          ByVal buff As bytes,
                          ByVal slice As storageInterface) As Boolean Implements storoomThreadModel.write
        Return slice.write(key, buff)
    End Function

    Public Function singleThreadWork(ByVal d As _do(Of Boolean)) As Boolean _
                                    Implements storoomThreadModel.singleThreadWork
        Return d()
    End Function

    Public Function callbackManager() As storoomCallbackManager Implements storoomThreadModel.callbackManager
        Return cbm
    End Function
End Class
